#include <stdio.h>
#include <string.h>

/*
光看题意，不限制!@#$这类字符。这里将单词理解为由连续的大小写拉丁字母组成的字符串
晕，题目还没限制单词的长度，我这里默认单词长度不超过100，总共单词数不超过1e4.
样例输入:
uxAesv!XiaEUDv Disjk  .&#a*      IDSsID

样例输出:
Disjk IDSsID XiaEUDv a uxAesv
*/

#define maxl 117
#define maxn 10017
char str[maxn][maxl];
int n, l, sub[maxn];
int is_head = 1;

//交换语句
void swap(int *x, int *y) {
	int t = *x; *x = *y; *y = t;
}

//判断字符是否是字母
int is_letter(char ch) {
	return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z');
}

//快速排序
//这里用了sub数组，本来是想着这样子swap字符串就变成了swap数字了，swap操作的复杂度从O(strlen)变成O(1)了
//后来发现这个优化没啥用，因为比较的复杂度也是O(strlen)，只能算是个常数优化
void QuickSort(int l, int r) {
	if(r <= l) return;
	int i = l - 1, j = r;
	while(1) {
		while(strcmp(str[sub[++i]], str[sub[r]]) < 0);
		while(strcmp(str[sub[--j]], str[sub[r]]) > 0) if(j == l) break;
		if(i >= j) break;
		swap(&sub[i], &sub[j]);
	}
	swap(&sub[i], &sub[r]);
	QuickSort(l, i - 1);
	QuickSort(i + 1, r);
}


int main() {
	//读入单词
	while(1) {
		char ch = getchar();
		if(ch == '\n') break;
		if(is_letter(ch)) {
			if(is_head) is_head = 0, n++, l = 0;
			str[n][l++] = ch; 
		}
		else {
			is_head = 1;
		}
	}
	for(int i = 1; i <= n; i++) printf("%s\n", str[i]);
	//sub数组，因为感觉快排里交换字符串比较花时间，所以用sub记录下标，对下标排序，这样快排代码里交换下表就行了。当然，字符串的交换和比较操作是同复杂度的，所以只能算是常数级优化。
	for(int i = 1; i <= n; i++) sub[i] = i;
	//排序
	QuickSort(1, n);
	for(int i = 1; i <= n; i++) printf("%s%c", str[sub[i]], " \n"[i == n]);
	return 0;
}